import pandas as pd
import numpy as np

def calculate_indicators(data):
    """计算丰富的技术指标"""
    if data is None or data.empty:
        return {}
    
    # 先定义safe_value函数，确保在使用前已定义
    def safe_value(value):
        if pd.isna(value):
            return None
        return value
    
    # 定义获取前一天值的安全函数
    def safe_prev_value(series, n=1):
        if len(series) <= n or pd.isna(series.iloc[-n]):
            return None
        return series.iloc[-n]

    # 计算更多移动平均线
    data['MA5'] = data['Close'].rolling(window=5).mean()
    data['MA10'] = data['Close'].rolling(window=10).mean()
    data['MA20'] = data['Close'].rolling(window=20).mean()
    data['MA30'] = data['Close'].rolling(window=30).mean()
    data['MA60'] = data['Close'].rolling(window=60).mean()
    data['MA120'] = data['Close'].rolling(window=120).mean()

    # 计算收益率
    data['Return'] = data['Close'].pct_change()
    data['Cumulative_Return'] = (1 + data['Return']).cumprod()

    # 计算波动率 (不同周期)
    data['Volatility_20'] = data['Return'].rolling(window=20).std() * np.sqrt(252)
    data['Volatility_60'] = data['Return'].rolling(window=60).std() * np.sqrt(252)

    # 计算RSI (默认14日，增加6日和21日)
    for period in [6, 14, 21]:
        delta = data['Close'].diff()
        gain = (delta.where(delta > 0, 0)).rolling(window=period).mean()
        loss = (-delta.where(delta < 0, 0)).rolling(window=period).mean()
        rs = gain / loss
        data[f'RSI_{period}'] = 100 - (100 / (1 + rs))
    
    # MACD指标
    exp1 = data['Close'].ewm(span=12, adjust=False).mean()
    exp2 = data['Close'].ewm(span=26, adjust=False).mean()
    data['MACD'] = exp1 - exp2
    data['Signal_Line'] = data['MACD'].ewm(span=9, adjust=False).mean()
    data['MACD_Hist'] = data['MACD'] - data['Signal_Line']
    
    # 布林带
    data['Middle_Band'] = data['Close'].rolling(window=20).mean()
    data['Std_Dev'] = data['Close'].rolling(window=20).std()
    data['Upper_Band'] = data['Middle_Band'] + (data['Std_Dev'] * 2)
    data['Lower_Band'] = data['Middle_Band'] - (data['Std_Dev'] * 2)
    data['Bollinger_Width'] = (data['Upper_Band'] - data['Lower_Band']) / data['Middle_Band']
    
    # KDJ指标 (随机指标)
    low_min = data['Low'].rolling(window=9).min()
    high_max = data['High'].rolling(window=9).max()
    data['RSV'] = (data['Close'] - low_min) / (high_max - low_min) * 100
    data['K'] = data['RSV'].ewm(com=2, adjust=False).mean()
    data['D'] = data['K'].ewm(com=2, adjust=False).mean()
    data['J'] = 3 * data['K'] - 2 * data['D']
    
    # 动量指标
    data['Momentum'] = data['Close'] - data['Close'].shift(10)
    data['ROC'] = (data['Close'] - data['Close'].shift(12)) / data['Close'].shift(12) * 100  # 变化率
    
    # 成交量指标
    data['Volume_MA5'] = data['Volume'].rolling(window=5).mean()
    data['Volume_MA20'] = data['Volume'].rolling(window=20).mean()
    data['Volume_Ratio'] = data['Volume'] / data['Volume_MA20']  # 量比
    
    # 能量潮(OBV)
    data['OBV'] = np.where(data['Close'] > data['Close'].shift(1), data['Volume'], 
                          np.where(data['Close'] < data['Close'].shift(1), -data['Volume'], 0)).cumsum()
    
    # 威廉指标(Williams %R)
    data['Williams_R'] = (high_max - data['Close']) / (high_max - low_min) * -100
    
    # 相对强弱指标（价格相对均线）
    data['MA_Ratio_5'] = data['Close'] / data['MA5'] - 1  # 当前价格相对于5日均线的偏离度
    data['MA_Ratio_20'] = data['Close'] / data['MA20'] - 1  # 当前价格相对于20日均线的偏离度
    
    # 均线斜率
    def calculate_slope(series, window=5):
        x = np.arange(window)
        slopes = []
        for i in range(len(series)):
            if i < window - 1:
                slopes.append(np.nan)
            else:
                y = series.iloc[i-window+1:i+1].values
                coeffs = np.polyfit(x, y, 1)
                slopes.append(coeffs[0])
        return pd.Series(slopes, index=series.index)
    
    data['MA5_Slope'] = calculate_slope(data['MA5'])
    data['MA20_Slope'] = calculate_slope(data['MA20'])
    
    # 日内波动范围
    data['Intraday_Range'] = (data['High'] - data['Low']) / data['Close'] * 100
    data['Avg_Range_10'] = data['Intraday_Range'].rolling(window=10).mean()
    
    latest = data.iloc[-1].to_dict()

    # 生成买入/卖出信号
    signals = {
        'buy_signals': [],
        'sell_signals': []
    }

    # 1. 均线金叉死叉 (多周期)
    for fast, slow in [(5, 20), (10, 30), (20, 60)]:
        if (not data[f'MA{fast}'].isna().iloc[-1] and 
            not data[f'MA{slow}'].isna().iloc[-1] and 
            len(data) > 1):
            if (data[f'MA{fast}'].iloc[-1] > data[f'MA{slow}'].iloc[-1] and 
                data[f'MA{fast}'].iloc[-2] <= data[f'MA{slow}'].iloc[-2]):
                signals['buy_signals'].append(f'MA{fast}/{slow}金叉')
            elif (data[f'MA{fast}'].iloc[-1] < data[f'MA{slow}'].iloc[-1] and 
                  data[f'MA{fast}'].iloc[-2] >= data[f'MA{slow}'].iloc[-2]):
                signals['sell_signals'].append(f'MA{fast}/{slow}死叉')
    
    # 2. RSI超买超卖
    for period in [6, 14, 21]:
        rsi_value = safe_value(data[f'RSI_{period}'].iloc[-1])
        if rsi_value is not None:
            if rsi_value < 30:
                signals['buy_signals'].append(f'RSI{period}超卖 ({rsi_value:.2f})')
            elif rsi_value > 70:
                signals['sell_signals'].append(f'RSI{period}超买 ({rsi_value:.2f})')
    
    # 3. MACD信号
    macd = safe_value(data['MACD'].iloc[-1])
    signal_line = safe_value(data['Signal_Line'].iloc[-1])
    prev_macd = safe_prev_value(data['MACD'])
    prev_signal = safe_prev_value(data['Signal_Line'])
    
    if macd is not None and signal_line is not None and prev_macd is not None and prev_signal is not None:
        if macd > signal_line and prev_macd <= prev_signal:
            signals['buy_signals'].append(f'MACD金叉 (MACD: {macd:.4f}, Signal: {signal_line:.4f})')
        elif macd < signal_line and prev_macd >= prev_signal:
            signals['sell_signals'].append(f'MACD死叉 (MACD: {macd:.4f}, Signal: {signal_line:.4f})')
    
    # 4. 布林带信号
    upper_band = safe_value(data['Upper_Band'].iloc[-1])
    lower_band = safe_value(data['Lower_Band'].iloc[-1])
    close_price = safe_value(data['Close'].iloc[-1])
    
    if upper_band is not None and lower_band is not None and close_price is not None:
        if close_price < lower_band:
            signals['buy_signals'].append('价格跌破布林带下轨')
        elif close_price > upper_band:
            signals['sell_signals'].append('价格突破布林带上轨')
    
    # 5. KDJ信号
    k = safe_value(data['K'].iloc[-1])
    d = safe_value(data['D'].iloc[-1])
    j = safe_value(data['J'].iloc[-1])
    
    if k is not None and d is not None:
        if k > d and k < 20:
            signals['buy_signals'].append(f'KDJ低位金叉 (K:{k:.2f}, D:{d:.2f})')
        elif k < d and k > 80:
            signals['sell_signals'].append(f'KDJ高位死叉 (K:{k:.2f}, D:{d:.2f})')
    
    if j is not None:
        if j < 0:
            signals['buy_signals'].append(f'J线超卖 ({j:.2f})')
        elif j > 100:
            signals['sell_signals'].append(f'J线超买 ({j:.2f})')
    
    # 6. 量价配合信号
    volume_ratio = safe_value(data['Volume_Ratio'].iloc[-1])
    price_change = safe_value(data['Return'].iloc[-1])
    
    if volume_ratio is not None and price_change is not None:
        if volume_ratio > 1.5 and price_change > 0.02:
            signals['buy_signals'].append(f'放量上涨 (量比:{volume_ratio:.2f},涨幅:{price_change:.2%})')
        elif volume_ratio > 1.5 and price_change < -0.02:
            signals['sell_signals'].append(f'放量下跌 (量比:{volume_ratio:.2f},跌幅:{price_change:.2%})')
    
    # 7. 威廉指标信号
    williams_r = safe_value(data['Williams_R'].iloc[-1])
    if williams_r is not None:
        if williams_r < -80:
            signals['buy_signals'].append(f'威廉指标超卖 ({williams_r:.2f})')
        elif williams_r > -20:
            signals['sell_signals'].append(f'威廉指标超买 ({williams_r:.2f})')
    
    # 8. 均线斜率信号
    ma5_slope = safe_value(data['MA5_Slope'].iloc[-1])
    ma20_slope = safe_value(data['MA20_Slope'].iloc[-1])
    
    if ma5_slope is not None and ma20_slope is not None:
        if ma5_slope > 0 and ma20_slope > 0 and ma5_slope > ma20_slope:
            signals['buy_signals'].append('均线多头排列')
        elif ma5_slope < 0 and ma20_slope < 0 and ma5_slope < ma20_slope:
            signals['sell_signals'].append('均线空头排列')
    
    return {
        # 基础价格信息
        'latest_price': safe_value(latest['Close']),
        'open_price': safe_value(latest['Open']),
        'high_price': safe_value(latest['High']),
        'low_price': safe_value(latest['Low']),
        'volume': safe_value(latest['Volume']),
        
        # 移动平均线
        'ma5': safe_value(latest['MA5']),
        'ma10': safe_value(latest['MA10']),
        'ma20': safe_value(latest['MA20']),
        'ma30': safe_value(latest['MA30']),
        'ma60': safe_value(latest['MA60']),
        'ma120': safe_value(latest['MA120']),
        'ma_slope_5': safe_value(latest['MA5_Slope']),
        'ma_slope_20': safe_value(latest['MA20_Slope']),
        'ma_ratio_5': safe_value(latest['MA_Ratio_5']),
        'ma_ratio_20': safe_value(latest['MA_Ratio_20']),
        
        # RSI指标
        'rsi_6': safe_value(latest['RSI_6']),
        'rsi_14': safe_value(latest['RSI_14']),
        'rsi_21': safe_value(latest['RSI_21']),
        
        # MACD指标
        'macd': safe_value(latest['MACD']),
        'signal_line': safe_value(latest['Signal_Line']),
        'macd_hist': safe_value(latest['MACD_Hist']),
        
        # 布林带
        'upper_band': safe_value(latest['Upper_Band']),
        'middle_band': safe_value(latest['Middle_Band']),
        'lower_band': safe_value(latest['Lower_Band']),
        'bollinger_width': safe_value(latest['Bollinger_Width']),
        
        # KDJ指标
        'kdj_k': safe_value(latest['K']),
        'kdj_d': safe_value(latest['D']),
        'kdj_j': safe_value(latest['J']),
        
        # 动量指标
        'momentum': safe_value(latest['Momentum']),
        'roc': safe_value(latest['ROC']),
        
        # 成交量指标
        'volume_ma5': safe_value(latest['Volume_MA5']),
        'volume_ma20': safe_value(latest['Volume_MA20']),
        'volume_ratio': safe_value(latest['Volume_Ratio']),
        'obv': safe_value(latest['OBV']),
        
        # 其他指标
        'williams_r': safe_value(latest['Williams_R']),
        'volatility_20': safe_value(latest['Volatility_20']),
        'volatility_60': safe_value(latest['Volatility_60']),
        'intraday_range': safe_value(latest['Intraday_Range']),
        'avg_range_10': safe_value(latest['Avg_Range_10']),
        'return_1d': safe_value(latest['Return']),
        'cumulative_return': safe_value(latest['Cumulative_Return']),
        
        # 交易信号
        'signals': signals
    }
